using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Security.AccessControl;
using System.Security.Permissions;
using System.Text;
using System.Windows;
using Microsoft.Win32;
using System.Configuration;
using System.Security.Cryptography;

// Must have permission to view and modify the registry:
[assembly: RegistryPermissionAttribute(SecurityAction.RequestMinimum, ViewAndModify = "HKEY_LOCAL_MACHINE")]

namespace MJB.UI.ContentEditor
{
    /// <summary>
    /// This class is bindable object that can be used to get and set configuration data from
    /// the configuration file.
    /// </summary>
    public class EditorSettings : DependencyObject
    {
        #region Member Variables
        #region Dependency Properties

        /// <summary>
        /// This is the XmlDirectory dependency property.
        /// </summary>
        public static DependencyProperty XmlDirectoryProperty = DependencyProperty.Register("XmlDirectory",
            typeof(string),
            typeof(EditorSettings),
            new PropertyMetadata(String.Empty));

        /// <summary>
        /// This is the FTP Url dependency property.
        /// </summary>
        public static DependencyProperty XmlManagementUrlProperty = DependencyProperty.Register("FTPUrl",
            typeof(string),
            typeof(EditorSettings),
            new PropertyMetadata(String.Empty));

        /// <summary>
        /// This is the FTP Username dependency property.
        /// </summary>
        public static DependencyProperty UserNameProperty = DependencyProperty.Register("FTPUserName",
            typeof(string),
            typeof(EditorSettings),
            new PropertyMetadata(String.Empty));

        /// <summary>
        /// This is the FTP Password dependency property.
        /// </summary>
        public static DependencyProperty PasswordProperty = DependencyProperty.Register("FTPPassword",
            typeof(string),
            typeof(EditorSettings),
            new PropertyMetadata(String.Empty));

        #endregion

        /// <summary>
        /// Not particularly secure, but secure enough for what we're doing.
        /// </summary>
        private string mByteKeyString = "April 5th, Philadelphia,";

        /// <summary>
        /// Also not particularly secure.
        /// </summary>
        private string mByteIVString = "May 20th";

        /// <summary>
        /// This is the path to our configuration settings in the registry.
        /// </summary>
        private string mRegistryPath = String.Empty;

        #endregion
        #region Constructor

        /// <summary>
        /// Creates the editor settings.
        /// </summary>
        public EditorSettings()
        {
        }

        #endregion
        #region Public Properties

        /// <summary>
        /// Gets / sets the Xml Directory property.
        /// </summary>
        public string XmlDirectory
        {
            get
            {
                return (string)GetValue(XmlDirectoryProperty);
            }
            set
            {
                SetValue(XmlDirectoryProperty, value);
            }
        }

        /// <summary>
        /// Gets / sets the FTP Url
        /// </summary>
        public string XmlManagementURL
        {
            get
            {
                return (string)GetValue(XmlManagementUrlProperty);
            }
            set
            {
                SetValue(XmlManagementUrlProperty, value);
            }
        }

        /// <summary>
        /// Gets / sets the FTP Url
        /// </summary>
        public string UserName
        {
            get
            {
                return (string)GetValue(UserNameProperty);
            }
            set
            {
                SetValue(UserNameProperty, value);
            }
        }

        /// <summary>
        /// Gets / sets the FTP password
        /// </summary>
        public string Password
        {
            get
            {
                return (string)GetValue(PasswordProperty);
            }
            set
            {
                SetValue(PasswordProperty, value);
            }
        }

        #endregion
        #region Public Methods

        /// <summary>
        /// Loads from the configuration file.
        /// </summary>
        public void LoadFromRegistry()
        {
            try
            {
                RegistryKey key = Registry.CurrentUser.OpenSubKey("Software", true);
                RegistryKey mjbSoftwareKey = key.OpenSubKey(@"MJB Software\Content Editor", true);

                if(mjbSoftwareKey == null)
                {
                    mjbSoftwareKey = key.CreateSubKey(@"MJB Software\Content Editor", RegistryKeyPermissionCheck.ReadWriteSubTree);
                    mjbSoftwareKey.SetValue("XmlDirectory", String.Empty);
                    mjbSoftwareKey.SetValue("XmlManagementURL", String.Empty);
                    mjbSoftwareKey.SetValue("UserName", String.Empty);
                    mjbSoftwareKey.SetValue("Password", new byte[] { });

                }

                using(mjbSoftwareKey)
                {
                    // Load the values from the registry:
                    this.XmlDirectory = (string)mjbSoftwareKey.GetValue("XmlDirectory");
                    this.XmlManagementURL = (string)mjbSoftwareKey.GetValue("XmlManagementURL");
                    this.UserName = (string)mjbSoftwareKey.GetValue("UserName");

                    byte[] encryptedPassword = (byte[])mjbSoftwareKey.GetValue("Password");

                    if(encryptedPassword.Length > 0)
                    {
                        TripleDES tripleDES = TripleDESCryptoServiceProvider.Create();
                        ICryptoTransform cryptoTransform = tripleDES.CreateDecryptor(Encoding.ASCII.GetBytes(mByteKeyString), Encoding.ASCII.GetBytes(mByteIVString));

                        // Create a stream to decrypt the encrypted string.
                        CryptoStream cryptoStream = new CryptoStream(new MemoryStream(encryptedPassword),
                            cryptoTransform,
                            CryptoStreamMode.Read);

                        StreamReader streamReader = new StreamReader(cryptoStream);
                        this.Password = streamReader.ReadToEnd();
                        streamReader.Dispose();

                    }

                }

            }
            catch(Exception e)
            {
                MessageBox.Show(Application.Current.MainWindow, e.Message, "Error");
            }

        }


        /// <summary>
        /// Saves to the configuration file.
        /// </summary>
        public void SaveToRegistry()
        {
            try
            {
                // Save values to the registry:    
                RegistryKey key = Registry.CurrentUser.OpenSubKey("Software", true);
                RegistryKey mjbSoftwareKey = key.OpenSubKey(@"MJB Software\Content Editor", true);

                using(mjbSoftwareKey)
                {
                    mjbSoftwareKey.SetValue("XmlDirectory", this.XmlDirectory, RegistryValueKind.String);
                    mjbSoftwareKey.SetValue("XmlManagementURL", this.XmlManagementURL, RegistryValueKind.String);
                    mjbSoftwareKey.SetValue("UserName", this.UserName, RegistryValueKind.String);

                    TripleDES tripleDES = TripleDESCryptoServiceProvider.Create();
                    ICryptoTransform cryptoTransform = tripleDES.CreateEncryptor(Encoding.ASCII.GetBytes(mByteKeyString), Encoding.ASCII.GetBytes(mByteIVString));

                    // Create a stream to decrypt the encrypted string.
                    MemoryStream memoryStream = new MemoryStream();
                    CryptoStream cryptoStream = new CryptoStream(memoryStream,
                        cryptoTransform,
                        CryptoStreamMode.Write);

                    StreamWriter streamWriter = new StreamWriter(cryptoStream);
                    streamWriter.Write(this.Password);
                    streamWriter.Close();

                    mjbSoftwareKey.SetValue(@"Password", memoryStream.ToArray(), RegistryValueKind.Binary);

                }

            }
            catch(Exception e)
            {
                MessageBox.Show(Application.Current.MainWindow, e.Message, "Error");
            }

        }

        #endregion

    }

}
